<template>
  <a-modal
    :visible="visible"
    title="证件读取"
    centered
    :footer="null"
    :width="720"
    :body-style="{
      padding: '24px 16px',
    }"
    :zIndex="1001"
    @cancel="onClose"
  >
    <a-row v-if="connected">
      <template v-if="cardInfo.certNumber">
        <a-button type="primary" @click="confirmClick">确认</a-button>
        <a-button
          type="primary"
          ghost
          @click="startRead"
          style="margin-left: 20px"
          >重新读取</a-button
        >
      </template>
      <template v-else>
        <a-button type="primary" @click="startRead">开始读取</a-button>
      </template>
    </a-row>

    <div class="spin-wrap" v-if="isReading">
      <a-spin size="large" />
      <div class="spin-tip1">正在读取中，请稍等</div>
      <div class="spin-tip2">请勿移动证件或断开设备</div>
    </div>
    <a-descriptions
      bordered
      size="middle"
      :column="2"
      class="desc-table"
      v-else-if="cardInfo.certNumber"
    >
      <a-descriptions-item label="证件类型">{{
        cardInfo.certType == 1
          ? "中国居民身份证"
          : cardInfo.certType == 50
          ? "外国人永久居住证证"
          : cardInfo.certType == 54
          ? "台湾居住证"
          : "港澳居住证"
      }}</a-descriptions-item>
      <a-descriptions-item label="中/英姓名">
        {{ cardInfo.partyName || "-" }}
      </a-descriptions-item>
      <a-descriptions-item label="性别">
        {{ cardInfo.gender == 1 ? "男" : "女" }}
      </a-descriptions-item>
      <a-descriptions-item label="民族/国籍">
        {{ cardInfo.nation || "-" }}
      </a-descriptions-item>
      <a-descriptions-item label="证件号码">
        {{ cardInfo.certNumber || "-" }}
      </a-descriptions-item>
      <a-descriptions-item label="出生日期">
        {{ cardInfo.bornDay || "-" }}
      </a-descriptions-item>
      <a-descriptions-item label="住址" :span="2">
        {{ cardInfo.certAddress || "-" }}
      </a-descriptions-item>
      <a-descriptions-item label="签发机关" :span="2">
        {{ cardInfo.certOrg }}
      </a-descriptions-item>
      <a-descriptions-item label="开始期限">
        {{ cardInfo.effDate || "-" }}
      </a-descriptions-item>
      <a-descriptions-item label="结束期限">
        {{ cardInfo.expDate || "-" }}
      </a-descriptions-item>
      <a-descriptions-item label="照片">
        <img
          :src="'data:image/jpeg;base64,' + cardInfo.identityPic"
          alt=""
          style="width: 60px; height: 50px; object-fit: contain"
          v-if="cardInfo.identityPic"
        />
      </a-descriptions-item>
    </a-descriptions>
    <div class="connected-wrap" v-else>
      <template v-if="connected === true">
        <CheckCircleOutlined class="connected-icon1" />
        <div class="connected-tip">设备连接成功，点击上方按钮开始读取证件</div>
      </template>
      <template v-if="connected === false">
        <CloseCircleOutlined class="connected-icon2" />
        <div class="connected-tip">设备连接失败，请检查设备或联系管理员</div>
      </template>
    </div>
  </a-modal>
</template>

<script>
import { defineComponent, reactive, toRefs, computed, watch } from "vue";
import { message } from "ant-design-vue";
import {
  CheckCircleOutlined,
  CloseCircleOutlined,
} from "@ant-design/icons-vue";
let CertCtl;
export default defineComponent({
  name: "IDCardReader",
  components: { CheckCircleOutlined, CloseCircleOutlined },
  props: {
    visible: {
      type: Boolean,
      default: false,
    },
  },

  setup(props, context) {
    const state = reactive({
      cardInfo: {},
      connected: null, //读卡器是否连接
      isReading: false, //是否正在读卡中
    });

    const onClose = () => {
      context.emit("onClose");
    };

    //创建XMLHttpRequest 对象，用于在后台与服务器交换数据
    const createXmlHttp = () => {
      var xmlHttp = null;
      //根据window.XMLHttpRequest对象是否存在使用不同的创建方式
      if (window.XMLHttpRequest) {
        xmlHttp = new XMLHttpRequest(); //FireFox、Opera等浏览器支持的创建方式
      } else if (window.ActiveXObject) {
        xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); //IE浏览器支持的创建方式
      }
      xmlHttp.withCredentials = false;
      return xmlHttp;
    };

    //连接读卡器
    const connect = () => {
      //创建请求 第一个参数是代表以post方式发送；第二个是请求端口和地址；第三个表示是否异步
      CertCtl.xhr.open("POST", "http://127.0.0.1:18889/api/connect", false);
      //发送请求
      try {
        CertCtl.xhr.send();
      } catch (e) {}
      //返回值readyState   0: 请求未初始化
      //				    1: 服务器连接已建立
      //				    2：请求已接收
      //				    3: 请求处理中
      //				    4: 请求已完成，且响应已就绪
      //返回值status      200: "OK"
      //					404: 未找到页面
      //当返回值readyState为4且status为200时,为查询成功
      if (CertCtl.xhr.readyState == 4 && CertCtl.xhr.status == 200) {
        //windows10上面无法解析
        let result = eval("(" + CertCtl.xhr.responseText + ")");
        //如果result为空,代表读卡插件未启动
        if (result == "") {
          message.error("未启动读卡插件!");
          state.connected = false;
        } else if (result.resultFlag == "0") {
          // 读卡器连接成功
          state.connected = true;
        } else {
          state.connected = false;
        }
      } else {
        state.connected = false;
        message.error("未启动读卡插件!");
      }
      context.emit("onConnect", state.connected);
    };

    //执行读卡操作
    const startRead = () => {
      state.cardInfo = {};
      state.isReading = true;
      setTimeout(() => {
        //创建请求 第一个参数是代表以post方式发送；第二个是请求端口和地址；第三个表示是否异步
        CertCtl.xhr.open("POST", "http://127.0.0.1:18889/api/readCard", false); //readCard读卡，不生成正反面仿复印件
        //CertCtl.xhr.open("POST", "http://127.0.0.1:18889/api/readCert", false);	  //readCert读卡，生成正反面仿复印件
        //发送请求
        CertCtl.xhr.send();
        if (CertCtl.xhr.readyState == 4 && CertCtl.xhr.status == 200) {
          //windows10上面无法解析
          let result = eval("(" + CertCtl.xhr.responseText + ")");
          //resultFlag为0代表读卡成功
          if (result.resultFlag == "0") {
            console.log("身份信息：", result.resultContent);
            message.success("读取成功");
            state.isReading = false;
            state.cardInfo = result.resultContent;
          } else {
            if (result.errorMsg == "端口打开失败") {
              message.error("读卡器未连接");
              state.isReading = false;
            } else {
              message.error(result.errorMsg);
              state.isReading = false;
            }
          }
        }
      }, 500);
    };

    const init = () => {
      //创建读卡控件
      CertCtl = {
        xhr: createXmlHttp(),
      };
      connect();
    };

    init();

    watch(
      () => props.visible,
      (val) => {
        if (val) {
          init();
        } else {
          state.cardInfo = {};
        }
      }
    );

    const confirmClick = () => {
      context.emit("confirm", state.cardInfo);
    };

    return {
      ...toRefs(state),
      onClose,
      startRead,
      confirmClick,
    };
  },
});
</script>

<style lang="less" scoped>
.desc-table {
  margin-top: 20px;

  :deep(.ant-descriptions-view table) {
    table-layout: fixed;
  }
}

.spin-wrap {
  width: 100%;
  height: 300px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;

  .spin-tip1 {
    margin-top: 30px;
  }

  .spin-tip2 {
    color: #999;
    margin-top: 10px;
  }
}

.connected-wrap {
  width: 100%;
  height: 300px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;

  .connected-icon1 {
    font-size: 40px;
    color: #87d068;
  }

  .connected-icon2 {
    font-size: 40px;
    color: #ff4d4f;
  }

  .connected-tip {
    margin-top: 20px;
    font-size: 16px;
  }
}
</style>
